package com.cnswhy.cloud.server.app.utils;

import cn.hutool.core.img.Img;
import com.cnswhy.cloud.common.redis.service.RedisService;
import com.cnswhy.cloud.server.core.constant.RedisConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * @author HuangHL
 * @date 2016/2/1
 * @see
 */
@Slf4j
public class FtpUtil
{
    

    private static FTPClient ftp;
    
    private static String ip;

    private static Integer port;

    private static String userName;

    private static String pwd;
    
 // 需要压缩的文件大小500k以上
    private static final long SCALA_SIZE = 1024 * 1024;
    
    
    public static void upload(File f, String dir, String ipAddr, int port, String userName, String pwd) throws Exception
    {
        if (connect(ipAddr, port, userName, pwd))
        {
            log.info("================>开始上传文件：");
            log.info("================>文件名称：" + f.getName());
            log.info("================>ftp_IP：" + ipAddr);
            log.info("================>ftp_PORT：" + port);
            log.info("================>用户名和密码：" + userName + " | " + pwd);
            ftp.changeToParentDirectory();
            boolean flag = ftp.changeWorkingDirectory(dir);
            if (!flag)
            {
                ftp.mkd(dir);
                ftp.changeWorkingDirectory(dir);
            }
            FileInputStream input = new FileInputStream(f);
            try
            {
                ftp.storeFile(new String(f.getName().getBytes("GBK"), "iso-8859-1"), input);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            
            input.close();
        }
        close();
    }
    
    private static void getFtpInfo(RedisService iJedisRedisProxy)
    {
        ip = String.valueOf(
                    iJedisRedisProxy.hget(RedisConstant.SYS_CONFIG_1, RedisConstant.FILE_FTP_IP));
        port = Integer.valueOf(String.valueOf(
                    iJedisRedisProxy.hget(RedisConstant.SYS_CONFIG_1, RedisConstant.FILE_FTP_PORT)));
        userName = String.valueOf(
                    iJedisRedisProxy.hget(RedisConstant.SYS_CONFIG_1, RedisConstant.FILE_FTP_USER));
        pwd = String.valueOf(
                    iJedisRedisProxy.hget(RedisConstant.SYS_CONFIG_1, RedisConstant.FILE_FTP_PWD));
    }
    
    /**
     * 获取ftp连接
     *
     * @return
     * @throws Exception
     */
    private static boolean connect(String ipAddr, int port, String userName, String pwd) throws Exception
    {
        if (ftp != null && ftp.isConnected())
        {
            ftp.disconnect();
        }
        ftp = new FTPClient();
        ftp.setDataTimeout(60000);
        ftp.setDefaultTimeout(60000);
        boolean flag = false;
        int reply;
        if (port == 0)
        {
            ftp.connect(ipAddr, 21);
        }
        else
        {
            ftp.connect(ipAddr, port);
        }
        ftp.login(userName, pwd);
        ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
        reply = ftp.getReplyCode();
        if (!FTPReply.isPositiveCompletion(reply))
        {
            ftp.disconnect();
            return flag;
        }
        flag = true;
        return flag;
    }
    
    /**
     * 关闭ftp连接
     */
    private static void close()
    {
        if (ftp != null && ftp.isConnected())
        {
            try
            {
                ftp.logout();
                ftp.disconnect();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
    
    public static void upload(File f, String dir, String ipAddr, int port, String userName, String pwd,String suffix) throws Exception
    {
        if (connect(ipAddr, port, userName, pwd))
        {
            ftp.changeToParentDirectory();
            boolean flag = ftp.changeWorkingDirectory(dir);
            if (!flag)
            {
                ftp.mkd(dir);
                ftp.changeWorkingDirectory(dir);
            }
            FileInputStream input = new FileInputStream(f);
            try
            {
                String fileName = f.getName() + suffix;
                ftp.storeFile(new String(fileName.getBytes("GBK"), "iso-8859-1"), input);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            
            input.close();
        }
        close();
    }
    
    /**
     * ftp上传文件
     *
     * @param f
     * @throws Exception
     */
    public static void upload(File f, String dir, RedisService iJedisRedisProxy) throws Exception
    {
        getFtpInfo(iJedisRedisProxy);
        if (connect(ip, port, userName, pwd))
        {
            ftp.changeToParentDirectory();
            boolean flag = ftp.changeWorkingDirectory(dir);
            if (!flag)
            {
                ftp.mkd(dir);
                ftp.changeWorkingDirectory(dir);
            }
            FileInputStream input = new FileInputStream(f);
            try
            {
                ftp.storeFile(new String(f.getName().getBytes("GBK"), "iso-8859-1"), input);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            
            input.close();
        }
        close();
    }
    
    public static void rename(String path, String fileName, String ipAddr, int port, String userName, String pwd)
            throws Exception
    {
        if (connect(ipAddr, port, userName, pwd))
        {
            String root = path.substring(0, path.lastIndexOf("/"));
            String newPath = root + "/" + fileName;
            ftp.rename(new String(path.getBytes("GBK"), "iso-8859-1"),
                    new String(newPath.getBytes("GBK"), "iso-8859-1"));
        }
        close();
    }
    
    
    public synchronized static void uploadMultipartFile(MultipartFile file, String dir, String fileName, String ipAddr,
                                                        int port, String userName, String pwd) throws Exception
    {
        log.info("================>开始上传文件：");
        log.info("================>文件名称：" + fileName);
        log.info("================>ftp_IP：" + ipAddr);
        log.info("================>ftp_PORT：" + port);
        log.info("================>用户名和密码：" + userName + " | " + pwd);
        InputStream input = null;
        ByteArrayOutputStream baos = null;
        try
        {
            if (connect(ipAddr, port, userName, pwd))
            {
                ftp.changeToParentDirectory();
                boolean flag = ftp.changeWorkingDirectory(dir);
                if (!flag)
                {
                    ftp.mkd(dir);
                    ftp.changeWorkingDirectory(dir);
                }
                log.info("================>ftp 路径：" + ftp.printWorkingDirectory());
                
                // 图片压缩
                if (file.getSize() > SCALA_SIZE)
                {
                    baos = new ByteArrayOutputStream();
                    Img.from(file.getInputStream()).setQuality(0.5f).write(baos);
                    input = new ByteArrayInputStream(baos.toByteArray());
                }
                else
                {
                    input = file.getInputStream();
                }
                
                ftp.enterLocalPassiveMode();
                ftp.storeFile(new String(fileName.getBytes("GBK"), "iso-8859-1"), input);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            close();
            if (input != null)
            {
                try
                {
                    input.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            
            if (baos != null)
            {
                try
                {
                    baos.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
    
    
    /**
     * 下载文件 此处开始执行
     * 
     * @param relativeLocalPath
     * @param ftpFile
     * @param outputStream
     * @throws Exception
     */
    public static void downLoadStart(String relativeLocalPath, FTPFile ftpFile, OutputStream outputStream,
            String fileName) throws Exception
    {
        if (StringUtils.isBlank(fileName))
        {
            fileName = ftpFile.getName();
        }
        outputStream = new FileOutputStream(relativeLocalPath + fileName);
        ftp.retrieveFile(new String(ftpFile.getName().getBytes(), "iso-8859-1"), outputStream);
        outputStream.flush();
        outputStream.close();
    }
    
    /**
     * 描述：下载文件
     * @param relativeLocalPath 本地存储文件夹路径
     * @param localName 本地存储文件名
     * @param ftpPath ftp文件夹路径
     * @param name ftp文件名
     */
    @SuppressWarnings("unused")
    public static void downLoad(String relativeLocalPath, String localName, String ftpPath, String name, String ipAddr,
            int port, String userName, String pwd) throws Exception
    {
        if (connect(ipAddr, port, userName, pwd))
        {
            ftp.changeToParentDirectory();
            ftp.changeWorkingDirectory(ftpPath);
            ftp.setControlEncoding("UTF-8");
            FTPFile[] files = ftp.listFiles();
            OutputStream outputStream = null;
            for (FTPFile ftpFile : files)
            {
                if (ftpFile.getName().equals(name))
                {
                    downLoadStart(relativeLocalPath, ftpFile, outputStream, localName);
                }
                else if ("image_File_Obj".equals(name))
                {
                    String dirHz = ftpFile.getName().substring(ftpFile.getName().lastIndexOf(".")).toLowerCase();
                    if (".png".equals(dirHz) || ".jpg".equals(dirHz) || ".jpeg".equals(dirHz) || ".gif".equals(dirHz)
                            || ".bmp".equals(dirHz))
                    {
                        downLoadStart(relativeLocalPath, ftpFile, outputStream, localName);
                    }
                }
                else if ("file_File_Obj".equals(name))
                {
                    downLoadStart(relativeLocalPath, ftpFile, outputStream, localName);
                }
            }
            try
            {
                if (outputStream != null)
                {
                    outputStream.close();
                }
            }
            catch (IOException e)
            {
                log.error("输出文件流异常");
            }
        }
        close();
    }
    
    /**
     * 删除文件
     *
     * @param filePath
     * @throws Exception
     */
    public static void delete(String filePath, String ipAddr, int port, String userName, String pwd) throws Exception
    {
        String path = filePath.substring(0, filePath.lastIndexOf(File.separator));
        String name = filePath.substring(filePath.lastIndexOf(File.separator) + 1, filePath.length());
        if (connect(ipAddr, port, userName, pwd))
        {
            ftp.changeWorkingDirectory(path);
            ftp.deleteFile(new String(name.getBytes(), "iso-8859-1"));
        }
        close();
    }
    
    /**
     * 描述：FTP判断文件是否存在
     * 作者：张进飞
     * 时间：2016年9月12日 下午4:30:06
     * @param ftpPath
     * @param fileName
     * @return
     * @throws Exception
     */
    public static boolean exists(String ftpPath, String fileName, String ipAddr, int port, String userName, String pwd)
            throws Exception
    {
        boolean falg = false;
        if (connect(ipAddr, port, userName, pwd))
        {
            ftp.changeToParentDirectory();
            ftp.changeWorkingDirectory(ftpPath);
            ftp.setControlEncoding("UTF-8");
            FTPFile[] files = ftp.listFiles();
            for (FTPFile ftpFile : files)
            {
                if (ftpFile.getName().equals(fileName))
                {
                    return true;
                }
            }
        }
        return falg;
    }
    
    /**
     * ftp上传文件
     *
     * @param file
     * @throws Exception
     */
    public synchronized static void uploadMultipartFile(MultipartFile file, String dir, String fileName, RedisService iJedisRedisProxy) throws Exception
    {
        getFtpInfo(iJedisRedisProxy);
        log.info("================>开始上传文件：");
        log.info("================>文件名称：" + fileName);
        log.info("================>ftp_IP：" + ip);
        log.info("================>ftp_PORT：" + port);
        log.info("================>用户名和密码：" + userName + " | " + pwd);
        if (connect(ip, port, userName, pwd))
        {
            ftp.changeToParentDirectory();
            boolean flag = ftp.changeWorkingDirectory(dir);
            if (!flag)
            {
                ftp.mkd(dir);
                ftp.changeWorkingDirectory(dir);
            }
            log.info("================>ftp 路径：" + ftp.printWorkingDirectory());
            InputStream input = file.getInputStream();
            try
            {
                ftp.storeFile(new String(fileName.getBytes("GBK"), "iso-8859-1"), input);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            
            input.close();
        }
        close();
    }
    
    /**
     * 下载文件 此处开始执行
     * 
     * @param filePath
     * @param fileName
     * @param ipAddr
     * @throws Exception  retrieveFileStream(String remote) 
     */
    public static InputStream downLoadInputStream(String filePath, String fileName, String ipAddr, int port,
            String userName, String pwd) throws Exception
    {
        
        if (connect(ipAddr, port, userName, pwd))
        {
            ftp.changeToParentDirectory();
            boolean flag = ftp.changeWorkingDirectory(filePath);
            if (!flag)
            {
                ftp.mkd(filePath);
                ftp.changeWorkingDirectory(filePath);
            }
            
            // 从ftp上获取ggw目录下的文件  
            FTPFile[] file = ftp.listFiles();
            
            // 遍历所有文件，匹配需要查找的文件
            for (int i = 0; i < file.length; i++)
            {
                
                // 匹配到则进入  
                if (file[i].getName().contains(fileName))
                {
                    // 将匹配到的文件流传入接口，转化成数组集合  
                    return ftp.retrieveFileStream(file[i].getName());
                    
                }
            }
            
        }
        close();
        
        return null;
    }
    
    /** 
     * 递归遍历目录下面指定的文件名 
     * @param pathName 需要遍历的目录，必须以"/"结束 
     * @param ext 文件的扩展名 
     * @throws Exception 
     */
    public static Map<String, String> readFile(String pathName, String ext, String ipAddr, int port, String userName,
            String pwd, Map<String, String> arFiles) throws Exception
    {
        if (!(connect(ipAddr, port, userName, pwd)))
        {
            return null;
        }
        if (arFiles == null)
        {
            arFiles = new HashMap<String, String>();
        }
        if (pathName.endsWith("/"))
        {
            String directory = pathName;
            //更换目录到当前目录  
            ftp.changeWorkingDirectory(directory);
            FTPFile[] files = ftp.listFiles();
            for (FTPFile file : files)
            {
                if (file.isFile())
                {
                    if (file.getName().endsWith(ext))
                    {
                        arFiles.put(directory, file.getName());
                    }
                }
                else if (file.isDirectory())
                {
                    readFile(directory + file.getName() + "/", ext, ipAddr, port, userName, pwd, arFiles);
                }
            }
        }
        return arFiles;
    }
    
    public static void main(String[] args)
    {
        try
        {
            downLoad("D://test/", "haha.txt", "/test/20180514/", "INT_D_WECHAT_APP_REGIST.txt", "192.168.0.192",
                    21, "uidp", "uidp");
        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
